#!/usr/bin/python3
"""
Configure kernel parameters at boot via sysctl.d.

This stage creates a sysctl.d configuration file with the given name in
/usr/lib/sysctl.d. Provided list of parameters is written as separate lines
into the configuration file. At least one parameter must be specified.

The syntax of the sysctl.d file is simply:
<token> = <value>

If a line begins with a single "-", any attempts to set the value that fail
will be ignored. (from sysct.conf(5) man page)

The <token> can be a glob pattern.

A key may be explicitly excluded from being set by any matching glob patterns
by specifying the key name prefixed with a "-" character and not followed
by "=". (from sysctl.d(5) man page)
"""


import sys

import osbuild.api


SCHEMA = r"""
"definitions": {
  "parameter": {
    "type": "object",
    "additionalProperties": false,
    "required": ["key", "value"],
    "description": "Kernel parameter to set.",
    "properties": {
      "key": {
        "type": "string",
        "description": "Kernel parameter name."
      },
      "value": {
        "type": "string",
        "description": "Kernel parameter value."
      }
    }
  },
  "parameter-excluded": {
    "type": "object",
    "additionalProperties": false,
    "required": ["key"],
    "description": "Parameter to exclude from being set by a matching glob",
    "properties": {
      "key": {
        "type": "string",
        "pattern": "^-.+$",
        "description": "Key to exclude from being set by a matching glob"
      }
    }
  }
},
"additionalProperties": false,
"required": ["filename", "config"],
"properties": {
  "filename": {
    "type": "string",
    "description": "Name of the sysctl.d configuration file to create.",
    "pattern": "^[\\w.-]{1,250}\\.conf$"
  },
  "config": {
    "additionalProperties": false,
    "type": "array",
    "description": "List of kernel parameters to write into the configuration file.",
    "minItems": 1,
    "items": {
      "anyOf": [
        {"$ref": "#/definitions/parameter"},
        {"$ref": "#/definitions/parameter-excluded"}
      ]
    }
  }
}
"""


def main(tree, options):
    filename = options["filename"]
    cfg = options["config"]

    sysctld_config_dir = f"{tree}/usr/lib/sysctl.d"

    cfg_lines = []
    for cfg_item in cfg:
        key = cfg_item["key"]
        value = cfg_item.get("value")
        cfg_line = f"{key} = {value}\n" if value else f"{key}\n"
        cfg_lines.append(cfg_line)

    with open(f"{sysctld_config_dir}/{filename}", "w") as f:
        f.writelines(cfg_lines)

    return 0


if __name__ == '__main__':
    args = osbuild.api.arguments()
    r = main(args["tree"], args["options"])
    sys.exit(r)
